﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace EventStandsApp
{
    public partial class Form1 : Form
    {
        //UI ui;
        EventStand es;
        Client c;
        Double total, deposit,initialdeposit;
        double virtualBalace;
        int numericVal;
        DataHelper dh;
        public Form1()
        {
            InitializeComponent();
            //ui = new UI(total, deposit, initialdeposit, numericVal,btnReturn,btnProcessOrder,btnClearOrder);
            dh= new DataHelper();
            //ui.initialize();
            initialize();
            DateTime endDate = Convert.ToDateTime("25-05-2013");
            numericUpDown1.Maximum = 3;//Convert.ToInt32(endDate.Subtract(DateTime.Today).TotalDays);
        }
       
        /* creates the EventStand object and also the Client object
         * displays information about the client
         * makes visible some buttons
         if the id that was entered doesn't exist or the input was wrong a message will be dispalyed*/
        private void btnEnterId_Click(object sender, EventArgs e) //enter client
        {
            //ui.btnEnterIdInit();
            btnEnterIdInit();
            listBox1.Items.Clear();
            listBox4.Items.Clear();
            int clientId = 0;
            try
            {
                clientId = Convert.ToInt32(textBox1.Text);
                es = new EventStand(1001, clientId, dh);
                c = es.getClient(clientId);
                if (c != null)
                {
                    loadEverythingForClient();
                    //ui.makeButtonsVisible();
                    makeButtonsVisible();
                }
                else { MessageBox.Show("the client id does not exist"); }
            }
            catch (FormatException exc) { MessageBox.Show(exc.Message); }
        }

        /* returns an item for a client
         * reloads the list of rented items for that client
         * updates the balance
         * if the end date of returned is ecpired a message will be displayed
         * if no item was selected before clicking the "return" button a message will be displayed*/
        private void btnReturn_Click(object sender, EventArgs e) //return item
        {
            try
            {
                string curItem = listBox4.SelectedItem.ToString();

                string[] arr;
                arr = curItem.Split(',');         // sperated by ","
                int prodId = Convert.ToInt32(arr[0]);
                if (c.returnItem(prodId) == true)
                {
                    MessageBox.Show("succes!");
                    DateTime end = Convert.ToDateTime(arr[6]);
                    RentedItem r = c.getItem(prodId);
                    returnItem(end, r);
                }
                else
                {
                    MessageBox.Show("Failed!");
                }
            }
            catch (Exception exc) { MessageBox.Show(exc.Message); }

        }

        /* clears the order by putting the total to zero, updating the balance of the client 
         * and restoring the items by updating the stock*/
        private void btnClearOrder_Click(object sender, EventArgs e) //clear order
        {
            virtualBalace = virtualBalace + deposit + total;
            label4.Text = "" + virtualBalace;
            for (int i = 0; i < listBox3.Items.Count; i++)
            {
                listBox3.SelectedIndex = i;
                string curItem = listBox3.Items[listBox3.SelectedIndex].ToString();
                string[] arr;
                arr = curItem.Split(',');         // sperated by ","
                int prodId = Convert.ToInt32(arr[0]);
                es.plusStock(prodId);
                RentedItem ri = es.getItem(prodId);
                ri.HowManyInOrder = 0;
            }
            loadItems();
            clearOrder();
        }

        /* process the order
         * update the balance of the client
         * adding the items of the order in the actual list
         * creates a new order
         * clears everything to zero*/
        private void btnProcessOrder_Click(object sender, EventArgs e)//process order
        {
            if (listBox3.Items.Count > 0)
            {
                int days = Convert.ToInt32(numericUpDown1.Value);
                c.Balance = virtualBalace;
                c.updateBalace();
                List<int> prodIds = new List<int>();
                for (int i = 0; i < listBox3.Items.Count; i++)
                {
                    listBox3.SelectedIndex = i;
                    string curItem = listBox3.Items[listBox3.SelectedIndex].ToString();
                    string[] arr;
                    arr = curItem.Split(',');         // sperated by ","
                    int prodId = Convert.ToInt32(arr[0]);
                    prodIds.Add(prodId);
                }
                Double price = total + deposit;
                es.addOrder(c, days, price, prodIds);
                MessageBox.Show("Order Processed!");
                reloadItemsClient();
                listBox3.Items.Clear();
                processOrder(prodIds);
            }
            else { MessageBox.Show("There is nothing in the order"); }
        }

        /*live search
         * searches for an item by its id
         * if no item is found a message will be dispalyed
         * checks for input*/
        private void btnSearch_Click(object sender, EventArgs e)
        {
            listBox2.ClearSelected();
            int index = listBox2.FindString(textBox2.Text);

            if (index < 0)
            {
                MessageBox.Show("Item not found.");
                textBox2.Text = String.Empty;
            }
            else
            {
                listBox2.SelectedIndex = index;
                //listBox2.SetSelected(index,true);
            } 
        }

        /* for adding or removing items from order
         * updates the balance of the client
         * updates the price, deposit and the total of the order
         * updates the stock
         * if an item isn't in stock anymore a message will be displayed
         * if the client doesn't have enough money a label will be dispalyed*/
        private void listBox2_MouseDown(object sender, MouseEventArgs e)
        {

            listBox2.SelectedIndex = listBox2.IndexFromPoint(e.X, e.Y);
            //string curItem = listBox2.SelectedItem.ToString();
            string curItem = listBox2.Items[listBox2.SelectedIndex].ToString();
            RentedItem r;
            
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                string[] arr;
                arr = curItem.Split(',');         // sperated by ","
                int prodId = Convert.ToInt32(arr[0]);
                r = es.getItem(prodId);
                if (findItemInOrderMinus(r, prodId) == true)
                {
                    r.UnitsInStock++;
                    loadItems();
                    minusInOrder(r);
                }
                
            }
            else
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    string[] arr;
                    arr = curItem.Split(',');         // sperated by ","
                    int prodId = Convert.ToInt32(arr[0]);
                    r= es.getItem(prodId);
                    if (r.UnitsInStock > 0)
                    {
                        if (r.UnitPrice * Convert.ToDouble(numericUpDown1.Value) + r.Deposit > virtualBalace)
                        {
                            label11.Visible = true;
                        }
                        else
                        {
                            label11.Visible = false;
                            r.UnitsInStock--;
                            listBox3.ClearSelected();
                            findItemInOrderPlus(r, arr);
                            loadItems();
                            plusInOrder(r);
                        }
                    }
                    else
                    {
                        MessageBox.Show("You need to redo the stock!");
                    }
                }

        }

        /* changes the number of days of an order
         * recalculates the total and updates the balance of the client
         * if the client doesn't have enough money a label will be dispalyed*/
        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
                if (numericVal > Convert.ToInt32(numericUpDown1.Value))
                {
                    if (label11.Visible == false)
                    {
                        virtualBalace = virtualBalace + initialdeposit;
                        total = initialdeposit * Convert.ToInt32(numericUpDown1.Value);
                    }
                    else
                    {
                        label11.Visible = false;
                    }
                }
                else
                {
                    double remainder = (initialdeposit * Convert.ToInt32(numericUpDown1.Value)) - total;
                    if (remainder > virtualBalace)
                    {
                        label11.Visible = true;
                    }
                    else
                    {
                        total = initialdeposit * Convert.ToInt32(numericUpDown1.Value);
                        virtualBalace = virtualBalace - initialdeposit;
                        label11.Visible = false;
                    }
                }
                numericUpDownSetLabels();
                numericVal = Convert.ToInt32(numericUpDown1.Value);
        }

        /* updates the stock of an item that is found after its id
         * checks for input*/
        private void btnRedoStock_Click(object sender, EventArgs e)
        {
            int itemId = 0;
            try
            {
                itemId = Convert.ToInt32(textBox2.Text);
                if (es.redoStock(itemId) == true)
                {
                    loadItems();
                }
                else { MessageBox.Show("the id doesn't exist!"); }
            }
            catch (FormatException exc) { MessageBox.Show(exc.Message); }
        }

        /*EXTRA METHODS*/
        /* initializes everything to zero
         * makes some buttons not visible: for returning an item, for processing order and for clearing the order*/
        public void initialize()
        {
            total = 0;
            deposit = 0;
            initialdeposit = 0;
            numericVal = 1;
            btnReturn.Visible = false;
            btnProcessOrder.Visible = false;
            btnClearOrder.Visible = false;
            label3.Text="";
            label4.Text="";
            label8.Text="0";
            label9.Text="0";
            label13.Text = "0";
        }

        /* sets the value of total, deposit and initialdeposit to zero; and numericVal to one*/
        public void btnEnterIdInit()
        {
            total = 0;
            deposit = 0;
            initialdeposit = 0;
            numericVal = 1;
        }

        /*makes three buttons visible: for returning an item, for processing order and for clearing the order*/
        public void makeButtonsVisible()
        {
            btnReturn.Visible = true;
            btnProcessOrder.Visible = true;
            btnClearOrder.Visible = true;
        }
        /* loads the items in the list from which you add to the order*/
        private void loadItems()
        {
            listBox2.Items.Clear();
            List<RentedItem> l = es.getAllItems();
            for (int i = 0; i < l.Count; i++)
            {
                listBox2.Items.Add(l[i].ProductId + "," + l[i].ProductName + ",  " + l[i].UnitPrice + ", " + l[i].UnitsInStock);
            }
        }

        /*shows the details of the client (like name, balance)
         * shows the items that the client rented in 2 list: one for returned and one for unreturned*/
        private void loadEverythingForClient()
        {
            List<RentedItem> l;
            loadItems();
            label3.Text = c.LastName + " " + c.FirstName;
            label4.Text = "" + c.Balance;
            virtualBalace = c.Balance;
            l = c.getReturnedItems();
            for (int i = 0; i < l.Count; i++)
            {
                Order o = es.getClientOrder(c.ClientId, l[i].ProductId);
                listBox1.Items.Add(l[i].ProductId + "," + l[i].ProductName + ", start date:"
                    + o.OrderDate.ToString("yyyy-MM-dd") + ", end date:" + o.OrderDate.AddDays(o.NoOfDays).ToString("yyyy-MM-dd"));
            }
            l = c.getUnreturnedItems();
            for (int i = 0; i < l.Count; i++)
            {
                Order o = es.getClientOrder(c.ClientId, l[i].ProductId);
                listBox4.Items.Add(l[i].ProductId + "," + l[i].ProductName + " Unitprice: " + l[i].UnitPrice + ", deposit: +" + l[i].Deposit + ", start date,"
                     + o.OrderDate.ToString("yyyy-MM-dd") + ", end date," + o.OrderDate.AddDays(o.NoOfDays).ToString("yyyy-MM-dd"));
            }
        }

        /*does the same thing like loadItemsClient, it just gets everything for the database again (in case of changes)*/
        private void reloadItemsClient()
        {
            int clientId = Convert.ToInt32(textBox1.Text);
            c = es.getClient(clientId);
            listBox1.Items.Clear();
            listBox4.Items.Clear();
            List<RentedItem> l = c.getReturnedItems();
            for (int i = 0; i < l.Count; i++)
            {
                Order o = es.getClientOrder(c.ClientId, l[i].ProductId);
                listBox1.Items.Add(l[i].ProductId + "," + l[i].ProductName + ", start date:"
                    + o.OrderDate.ToString("yyyy-MM-dd") + ", end date:" + o.OrderDate.AddDays(o.NoOfDays).ToString("yyyy-MM-dd"));
            }
            l = c.getUnreturnedItems();
            for (int i = 0; i < l.Count; i++)
            {
                Order o = es.getClientOrder(c.ClientId, l[i].ProductId);
                listBox4.Items.Add(l[i].ProductId + "," + l[i].ProductName + " Unitprice: " + l[i].UnitPrice + ", deposit: +" + l[i].Deposit + ", start date,"
                     + o.OrderDate.ToString("yyyy-MM-dd") + ", end date," + o.OrderDate.AddDays(o.NoOfDays).ToString("yyyy-MM-dd"));
            }
        }

        /* updates the balance of the client
         * checks if the end date for the item expired and shows a message*/
        private void returnItem(DateTime end, RentedItem r)
        {
            int diff = Convert.ToInt32(end.Subtract(DateTime.Today).TotalDays);
            if (diff >= 0)
            {
                c.Balance += (diff * r.UnitPrice) + r.Deposit;
                c.updateBalace();
                es.lowerMoneySpent(c, (diff * r.UnitPrice) + r.Deposit);
            }
            else
            {
                MessageBox.Show("Your end date has expired! You have lost your deposit!");
            }
            virtualBalace = c.Balance;
            label4.Text = "" + c.Balance;
            reloadItemsClient();
            es.updateUnitsInStock(r);
            loadItems();
        }

        /* sets everything to zero; or one for numericVal*/
        private void clearOrder()
        {
            listBox3.Items.Clear();
            total = 0;
            deposit = 0;
            initialdeposit = 0;
            numericVal = 1;
            numericUpDown1.Value = 1;
            label8.Text = "";
            label9.Text = "";
            label13.Text = "";
            label11.Visible = false;
        }

        /* sets everything to zero; or one for numericVal*/
        private void processOrder(List<int> prodIds)
        {
            total = 0;
            deposit = 0;
            initialdeposit = 0;
            numericVal = 1;
            label8.Text = "" + deposit;
            label9.Text = "" + total;
            label13.Text = "" + total;
            numericUpDown1.Value = 1;
            for (int i = 0; i < prodIds.Count; i++)
            {
                RentedItem ri = es.getItem(prodIds[i]);
                ri.HowManyInOrder = 0;
            }
        }

        /*udates the prices, total and balance of client*/
        private void plusInOrder(RentedItem r)
        {
            deposit += r.Deposit;
            initialdeposit += r.UnitPrice;
            total += r.UnitPrice * Convert.ToDouble(numericUpDown1.Value);
            label8.Text = "" + deposit;
            label9.Text = "" + total;
            label13.Text = "" + (deposit + total);
            virtualBalace = virtualBalace - r.Deposit - r.UnitPrice * Convert.ToDouble(numericUpDown1.Value);
            label4.Text = "" + virtualBalace;
        }

        /*adds an item into the order list; if the item is already there, just increase the number HowManyInOrder*/
        private void findItemInOrderPlus(RentedItem r, string[] arr)
        {
            int index = listBox3.FindString(arr[0]);
            if (index >= 0)
            {
                listBox3.SelectedIndex = index;
                r.HowManyInOrder++;
                listBox3.Items[listBox3.SelectedIndex] = r;
            }
            else
            {
                r.HowManyInOrder++;
                listBox3.Items.Add(r.ToString());
            }
        }

        /*removes an item into the order list; if the item is already there, just decrease the number HowManyInOrder
         *if it's only one item, it wil be removed from the list*/
        private bool findItemInOrderMinus(RentedItem r, int prodId)
        {
            int index = listBox3.FindString(prodId.ToString());
            listBox3.ClearSelected();
            if (index >= 0)
            {
               
                listBox3.SelectedIndex = index;
                r.HowManyInOrder--;
                if (r.HowManyInOrder > 0)
                {
                    listBox3.Items[listBox3.SelectedIndex] = r;
                }
                else
                {
                    listBox3.Items.RemoveAt(index);
                }
                return true;
            }
            return false;
        }

        /*udates the prices, total and balance of client*/
        private void minusInOrder(RentedItem r)
        {
            deposit -= r.Deposit;
            total -= r.UnitPrice * Convert.ToDouble(numericUpDown1.Value);
            initialdeposit -= r.UnitPrice;
            label8.Text = "" + deposit;
            label9.Text = "" + total;
            label13.Text = "" + (deposit + total);
            virtualBalace = virtualBalace + r.Deposit + r.UnitPrice;
            label4.Text = "" + virtualBalace;
        }

        /*sets the labels for balance, total and price*/
        private void numericUpDownSetLabels()
        {
            label4.Text = "" + virtualBalace;
            label9.Text = "" + total;
            label13.Text = "" + (deposit + total);
        }
    }
}
